#pragma once 
#ifndef __SWIG__
#include <vector>
#include <map>
#else
#include "D3D11_swig.h"
#endif


#ifdef __SWIG__
%include <typemaps.i>
%include "mui_typemap.i"

%apply SWIGTYPE** OUTPUT {ID2D1RenderTarget** ppD2DRenderTarget};
%apply SWIGTYPE** OUTPUT {ID2D1Bitmap** ppD2DBitmap};
%apply SWIGTYPE** OUTPUT { ID3D11UnorderedAccessView** ppUnorderAccessView};
%apply SWIGTYPE** OUTPUT { ID3D11ShaderResourceView** ppShaderResourceView};
%apply SWIGTYPE** OUTPUT { ID3D11RenderTargetView** ppRenderTargetView};
%apply SWIGTYPE** OUTPUT { IDXGISurface1** ppDXGISurface};
%apply SWIGTYPE** OUTPUT { ID3D11DepthStencilView** ppDepthStencilView};
%apply SWIGTYPE** OUTPUT { IDXGIKeyedMutex** ppKeyMutex};
%apply SWIGTYPE& OUTPUT {HANDLE& hResource}
#endif



#include "CDXDevice.h"
#include "CComm.h"

class CDXResource : public CDXBase, public CCritSec, public CRefCount
{
private:
	LONG m_nKeyMutex10LockCount;
	LONG m_nKeyMutex11LockCount;
protected:
	std::vector<ID3D11RenderTargetView*> m_pRenderTargetView;
	std::vector<ID3D11ShaderResourceView*> m_pShaderResourceView;
	std::vector<ID3D11UnorderedAccessView*> m_pUnorderedAccessView;
	std::vector<ID3D11DepthStencilView*>  m_pDepthStencilView;
	ID3D11RenderTargetView* m_pDefaultRTV;
	ID3D11ShaderResourceView* m_pDefaultSRV;
	ID3D11UnorderedAccessView* m_pDefaultUAV;
	ID3D11DepthStencilView* m_pDefaultDSV;

	ID2D1RenderTarget* m_pD2DRenderTarget;
	//D2D resouce are device-dependence
	std::map<ID2D1RenderTarget*, ID2D1Bitmap*> m_pD2DBitmap;  
	std::map<ID2D1RenderTarget*, ID2D1BitmapBrush*> m_pD2DBitmapBrush;	
	
	HANDLE m_hShareHandle;
	IDXGISurface1* m_pDXGISurface10;
	IDXGISurface1* m_pDXGISurface11;
	IDXGIKeyedMutex* m_pKeyMutex10;
	IDXGIKeyedMutex* m_pKeyMutex11;


protected:

	virtual HRESULT ReleaseResources();
	virtual BOOL IsEqual(const D3D11_RENDER_TARGET_VIEW_DESC& desc1, const D3D11_RENDER_TARGET_VIEW_DESC& desc2);
	virtual BOOL IsEqual(const D3D11_SHADER_RESOURCE_VIEW_DESC& desc1, const D3D11_SHADER_RESOURCE_VIEW_DESC& desc2);
	virtual BOOL IsEqual(const D3D11_UNORDERED_ACCESS_VIEW_DESC& desc1, const D3D11_UNORDERED_ACCESS_VIEW_DESC& desc2);
	virtual BOOL IsEqual(const D3D11_DEPTH_STENCIL_VIEW_DESC& desc1, const D3D11_DEPTH_STENCIL_VIEW_DESC& desc2);
public:
	CDXResource(CDXDevice* pDevice);
	virtual ~CDXResource();
	virtual ID3D11Resource* GetResource() const = 0;

	virtual HRESULT GetD2DRenderTarget(ID2D1RenderTarget** ppD2DRenderTarget);
	
	virtual HRESULT GetD2DBitmap(ID2D1RenderTarget* pRenderTarget, ID2D1Bitmap** ppD2DBitmap);
	virtual HRESULT GetD2DBitmapBrush(ID2D1RenderTarget* pRenderTarget, ID2D1BitmapBrush** pBrush);
	virtual HRESULT ClearD2DBitmapCache(ID2D1RenderTarget* pRenderTarget);
	virtual HRESULT ClearD2DBitmapBrushCache(ID2D1RenderTarget* pRenderTarget);

	virtual HRESULT GetRenderTargetView(D3D11_RENDER_TARGET_VIEW_DESC* pDesc, ID3D11RenderTargetView** ppRenderTargetView);
	virtual HRESULT GetShaderResourceView(D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, ID3D11ShaderResourceView** ppShaderResourceView);
	virtual HRESULT GetUnorderedAccessView(D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, ID3D11UnorderedAccessView** ppUnorderedAccessView);
	virtual HRESULT GetDepthStencilView(D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc, ID3D11DepthStencilView** ppDepthStencilView);



	virtual HRESULT GetDXGISurface10(IDXGISurface1** ppDXGISurface);
	virtual HRESULT GetDXGISurface11(IDXGISurface1** ppDXGISurface);
	virtual HRESULT GetKeyMutex10(IDXGIKeyedMutex** ppKeyMutex);
	virtual HRESULT GetKeyMutex11(IDXGIKeyedMutex** ppKeyMutex);
	virtual BOOL IsKeyMutexShared();
	virtual HRESULT GetShareHandle(HANDLE& hResource);
	virtual HRESULT OpenShareHandle(HANDLE hResource);

	virtual HRESULT CopyFrom(const CDXResource* pResource);
	virtual HRESULT CopySubresourceRegion(UINT DstSubresource, UINT DstX, UINT DstY, UINT DstZ, CDXResource* pSrcResource, 
		UINT SrcSubresource, const D3D11_BOX *pSrcBox);
	virtual HRESULT ClearColor(FLOAT color[4]);

	virtual HRESULT KeyMutex11Acquire();
	virtual HRESULT KeyMutex11Release();
	virtual HRESULT KeyMutex10Acquire();
	virtual HRESULT KeyMutex10Release();
};

class CDXRenderResourceLocker
{
protected:
	BOOL m_bDrawCmdQueue10Locked;
	std::vector<CDXResource*> m_DrawCmdResourceQueue10; // since the keymutex need to be locked when calling end draw, we need a queue to collect them.
	BOOL m_bDrawCmdQueue11Locked;
	std::vector<CDXResource*> m_DrawCmdResourceQueue11; // since the keymutex need to be locked when calling end draw, we need a queue to collect them.
protected:
	virtual HRESULT _PushDrawCmdResource10(CDXResource* pResource);
	virtual HRESULT _PushAndLockDrawCmdResource10(CDXResource* pResource);

	virtual HRESULT _PushDrawCmdResource11(CDXResource* pResource);
	virtual HRESULT _PushAndLockDrawCmdResource11(CDXResource* pResource);
public:
	CDXRenderResourceLocker();
	virtual ~CDXRenderResourceLocker();
	virtual HRESULT LockDrawCmdResource10();
	virtual HRESULT UnLockAndClearDrawCmdResource10();
	virtual HRESULT LockDrawCmdResource11();
	virtual HRESULT UnLockAndClearDrawCmdResource11();


};